package ithink.link.base.message;

import com.alibaba.fastjson.JSONObject;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import ithink.link.base.utils.ByteHelper;
import ithink.link.base.utils.DESUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * Created by zaqb on 17-10-24.
 */
public class LinkMessageDecoder extends ByteToMessageDecoder {

    private static final Logger LOGGER = LoggerFactory.getLogger( LinkMessageDecoder.class);
    private String fixedKey = "";

    private byte[] header = new byte[LinkMessage.INTERACTIVE_HEADER_LEN];
   // private byte[] body = new byte[LinkMessage.INTERACTIVE_MAX_BODY_LEN];
    private ByteBuf body = PooledByteBufAllocator.DEFAULT.heapBuffer(1024);
    private ByteBuf tmp = PooledByteBufAllocator.DEFAULT.heapBuffer(1024);
    private ByteBuf out = PooledByteBufAllocator.DEFAULT.heapBuffer(1024);

    private DESUtils desUtils = new DESUtils();
    public String getFixedKey() {
        return fixedKey;
    }

    public void setFixedKey(String fixedKey) {
        this.fixedKey = fixedKey;
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        body.release();
        tmp.release();
        out.release();
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        Object decoded = this.decode(ctx, in);
        if(decoded != null){
            out.add(decoded);

        }
    }

    private Object decode(ChannelHandlerContext ctx, ByteBuf in) {
        int length = in.readableBytes();
        if(length < 3) {
            return null;
        }
        byte flag = in.getByte(in.readerIndex());
        if(flag != LinkMessage.FLAG_RANDOM_KEY && flag != LinkMessage.FLAG_PART_KEY) {
            //error
            throw new RuntimeException(String.format("get error flag from %s flag = %d", ctx.channel().remoteAddress().toString(), flag));
        }
        int len = in.getInt(in.readerIndex() + 4);
        len = ByteHelper.toBigEndian(len);
        if(length < len + LinkMessage.INTERACTIVE_HEADER_LEN) {
            return null;
        }else if(len > LinkMessage.INTERACTIVE_MAX_BODY_LEN){
            //
            throw new RuntimeException(String.format("get error len from %s len = %d", ctx.channel().remoteAddress().toString(), len));
        }else {
            //读走包头咯
            if(body.capacity() < len) {
                body.release();
                out.release();
                tmp.release();
                body = PooledByteBufAllocator.DEFAULT.heapBuffer(len);
                out = PooledByteBufAllocator.DEFAULT.heapBuffer(len);
                tmp = PooledByteBufAllocator.DEFAULT.heapBuffer(len);
            }
            try {
                short version = in.getShort(in.readerIndex() + 2);
                version = ByteHelper.toBigEndian(version);
                in.readBytes(header, 0, LinkMessage.INTERACTIVE_HEADER_LEN);
                String randomKey = new String(header,8, 4);
                in.readBytes(body.array(), 0, len);
                LinkMessage pkg = new LinkMessage();
                String key = fixedKey + randomKey;
                if(flag == LinkMessage.FLAG_RANDOM_KEY) {
                    key = new String( header, 8, 8 );
                }
                String text = desUtils.Decode(body.array(), out.array(), tmp.array(), key, len);
                System.out.println(text);
                JSONObject jobj = JSONObject.parseObject(text);
                pkg.setText(jobj);
                pkg.setFlag(flag);
                pkg.setLen(len);
                pkg.setVersion( version );
                return pkg;
            } catch (Exception e) {
                LOGGER.error("decode error {}", e);
                return null;
            }finally{
                //body.release();
            }
        }

    }

}
